package com.example.utils;

import com.example.config.CodePathConfig;
import com.example.pojo.sandbox.ExecuteMessage;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static cn.hutool.core.io.FileUtil.*;


// 文件工具类
@Component
public class FileUtils {

    @Resource
    private CodePathConfig codePath;
    @Resource
    private ProcessUtils processUtils;

    // 保存代码到文件
    public File saveCodeToFile(String code, String filename) {
        String globalPathName = codePath.getCodePath();
        // 创建存储代码的文件夹
        if (!exist(globalPathName)) {
            mkdir(globalPathName);
        }
        // 将用户代码隔离存放并返回文件地址
        String userCodeParentPath = globalPathName + File.separator + UUID.randomUUID().toString().replaceAll("_", "");
        String userCodePath = userCodeParentPath + File.separator + filename;
        return writeString(code, userCodePath, StandardCharsets.UTF_8);
    }


    // 编译代码文件等待运行
    public ExecuteMessage compileCodeFile(String compileCmd) {
        try {
            // 根据编译命令获取编译进程
            Process compileProcess = Runtime.getRuntime().exec(compileCmd);
            // 调用进程工具类执行进程获取返回信息
            ExecuteMessage executeMessage = processUtils.runProcessAndGetMessage(compileProcess);
            if (executeMessage.getExitValue() != 0) {
                throw new RuntimeException("编译错误");
            }
            return executeMessage;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // 运行编译后的文件
    public List<ExecuteMessage> runCodeFile(String runCmd, List<String> inputList, long timeout) {
        // 封装每组测试数据返回信息
        List<ExecuteMessage> executeMessageList = new ArrayList<>();
        try {
            if (inputList.isEmpty()) {
                // 创建进程执行运行命令
                Process runProcess = Runtime.getRuntime().exec(runCmd);
                // 超时控制(超过最大等待时间结束进程)
                timeControl(runProcess, timeout);
                // 调用进程工具类获取进程执行结果并封装至返回信息
                ExecuteMessage executeMessage = processUtils.runProcessAndGetMessage(runProcess);
                executeMessageList.add(executeMessage);
            } else {
                for (String input : inputList) {
                    // 创建进程执行运行命令
                    Process runProcess = Runtime.getRuntime().exec(runCmd);
                    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(runProcess.getOutputStream()));
                    bufferedWriter.write(input);
                    bufferedWriter.flush();
                    bufferedWriter.close();
                    // 超时控制(超过最大等待时间结束进程)
                    timeControl(runProcess, timeout);
                    // 调用进程工具类获取进程执行结果并封装至返回信息
                    ExecuteMessage executeMessage = processUtils.runProcessAndGetMessage(runProcess);
                    executeMessageList.add(executeMessage);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return executeMessageList;
    }

    // 根据路径删除文件
    public boolean clearFile(File userCodeFile) {
        // 判断文件是否存在
        if (exist(userCodeFile)) {
            // 获取父一级目录
            String userCodeParentPath = userCodeFile.getParentFile().getParentFile().getAbsolutePath();
            // 删除文件
            del(userCodeParentPath);
            return true;
        }
        return true;
    }

    // 进程超时控制
    private void timeControl(Process process, long timeout) {
        new Thread(() -> {
            try {
                Thread.sleep(timeout);
                process.destroy();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }

}
